package com.frank.loadinglibrary.special.cool.ball;

import com.frank.loadinglibrary.special.cool.CoolLoadingComponent;
import com.frank.loadinglibrary.utils.SimpleAnimatorListener;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;

public class ForthCoolBall extends CoolBall {

    // 第一个圆或圆环或圆弧的半径和画笔大小
    private float mFiCurR;
    private float mFiStrokeWidth;
    // 第二个圆或圆环或圆弧的半径和画笔大小
    private float mSeCurR;
    private float mSeStrokeWidth;
    // 正常圆(能停留的)最小的直径
    private int STANDARD_MIN_R;
    // 前一个值
    private float mPreValue;
    // 当前值
    private float mCurValue;
    // 差值
    private float mDifValue;
    private Paint mPaint;
    private int mState = 1;
    private RectFloat mRectF;
    private float mAngle;
    private float mSweepAngle = 360;
    // 蓝色弧线的颜色渲染
    private SweepShader mSweepGradient;
    private AnimatorGroup mAnimatorSet;
    private boolean isStart = false;
    //
    private RadialShader mRadialGradient;
    // 时间值
    private int mDuration1 = 600;
    private int mDuration2 = 1000;
    private int mDuration3 = 2000;
    private int mDuration4 = 1000;
    private int mDuration5 = 1200;
    private int mDuration6 = 200;

    private int mEndCirIRadius;
    private int mEndCirMRadius;
    private int mEndCirORadius;
    private AnimatorValue mEndAnimator;
    // 正在结束,只绘制结束动画
    private boolean isMoveEnd = false;

    public ForthCoolBall(float x, float y) {
        super(x, y);

    }

    @Override
    protected void initConfig() {
        super.initConfig();
        init();
        initAnim();
    }

    private void init() {
        mEndMovingLength = 145;

        STANDARD_MIN_R = 15;
        mFiCurR = MAX_RADIUS_CIRCLE;
        mFiStrokeWidth = 33;
        mSeCurR = 0;
        mSeStrokeWidth = mSeCurR;

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE_STYLE);
    }

    @Override
    public void reset() {
        super.reset();
        isMoveEnd = false;
        // 初始化黄色小球
        STANDARD_MIN_R = 15;
        mFiCurR = MAX_RADIUS_CIRCLE;
        mFiStrokeWidth = 33;
        mSeCurR = 0;
        mSeStrokeWidth = mSeCurR;

    }

    @Override
    public void drawSelf(Canvas canvas) {
        super.drawSelf(canvas);
        if (!isMoveEnd) {
            switch (mState) {
                case 1:
                    // 绘制黄色圆环或圆
                    mPaint.setStrokeWidth(mFiStrokeWidth);
                    mPaint.setColor(CoolLoadingComponent.YELLOW);
                    canvas.drawCircle(getCurX(), getCurY(), mFiCurR - mFiStrokeWidth / 2, mPaint);
                    // 绘制绿色圆环
                    mPaint.setStrokeWidth(mSeStrokeWidth);
                    mPaint.setColor(CoolLoadingComponent.GREEN);
                    canvas.drawCircle(getCurX(), getCurY(), mSeCurR - mSeStrokeWidth / 2, mPaint);
                    break;
                case 2:

                    // 绘制蓝色弧线
                    canvas.save();
                    canvas.rotate(mAngle - 90, getCurX(), getCurY());
                    mPaint.setShader(mSweepGradient, Paint.ShaderType.SWEEP_SHADER);
                    canvas.drawCircle(getCurX(), getCurY(), mFiCurR - mFiStrokeWidth / 2, mPaint);
                    canvas.restore();

                    // 绘制黄色弧线
                    mPaint.setShader(null, Paint.ShaderType.SWEEP_SHADER);
                    mPaint.setStrokeWidth(mFiStrokeWidth);
                    mPaint.setColor(CoolLoadingComponent.YELLOW);
                    canvas.drawArc(mRectF, new Arc(mAngle - 90, mSweepAngle, false), mPaint);

                    // 绘制绿色圆环
                    mPaint.setStrokeWidth(mSeStrokeWidth);
                    mPaint.setColor(CoolLoadingComponent.GREEN);
                    canvas.drawCircle(getCurX(), getCurY(), mSeCurR - mSeStrokeWidth / 2, mPaint);
                    break;
                case 3:
                    // 绘制绿色圆环
                    mPaint.setStrokeWidth(mSeStrokeWidth);
                    mPaint.setShader(mRadialGradient, Paint.ShaderType.RADIAL_SHADER);
                    canvas.drawCircle(getCurX(), getCurY(), mSeCurR - mSeStrokeWidth / 2, mPaint);
                    mPaint.setShader(null, Paint.ShaderType.RADIAL_SHADER);
                    break;
                default:
                    break;
            }
        }

        if (mIsEnd) {
            if (!mIsEndAnimStart) {
                mEndAnimator.start();
                mIsEndAnimStart = true;
            }
            mPaint.setStyle(Paint.Style.FILL_STYLE);
            mPaint.setColor(CoolLoadingComponent.YELLOW);
            canvas.drawCircle(getCurX(), getCurY(), mEndCirIRadius, mPaint);
            mPaint.setColor(CoolLoadingComponent.BLUE);
            canvas.drawCircle(getCurX(), getCurY(), mEndCirMRadius, mPaint);
            mPaint.setColor(CoolLoadingComponent.GREEN);
            canvas.drawCircle(getCurX(), getCurY(), mEndCirORadius, mPaint);
            mPaint.setStyle(Paint.Style.STROKE_STYLE);
            return;
        }
    }

    @Override
    protected void initAnim() {
        mAnimatorSet = new AnimatorGroup();
        // 黄色圆环,内部绿色小球由无变大到圆环,仍然在黄色圆弧内
        Animator anim1 = createInsideCircleAnim();
        // 黄色圆环旋转为圆弧,带有一点蓝色的尾巴,逐渐缩短,绿色圆膨胀一些,变为圆环
        Animator anim2 = createRotateAnim();
        // 等待小球的到来,黄色圆弧彻底消失,绿色圆弧变为实心圆
        Animator anim3 = createWaitAndFillAnim();
        // 填充,等待一会,缩小然后放大
        Animator anim4 = createSmallBiggerAnim();
        // 圆环颜色由内向外拓展为蓝色.颜色由浅逐渐变深,一半的时候,内拓为红色,再到黄色,最后全黄,回到第一步
        Animator anim5 = createColorfulAnim();

        Animator anim6 = createPassAnim();

        mAnimatorSet.runSerially(anim1, anim2, anim3, anim4, anim5, anim6
        );
        mAnimatorSet.setStateChangedListener(new SimpleAnimatorListener() {
            @Override
            public void onEnd(Animator animator) {
                super.onEnd(animator);
                STANDARD_MIN_R = 15;
                mFiCurR = MAX_RADIUS_CIRCLE;
                mFiStrokeWidth = 33;
                mSeCurR = 0;
                mSeStrokeWidth = mSeCurR;
                if (mAnimatorStateListen != null) {
                    mAnimatorStateListen.onAnimatorEnd();
                }
            }
        });
    }

    /**
     * 第一步:黄色圆环,内部绿色小球由无变大到圆环,仍然在黄色圆弧内
     */
    public Animator createInsideCircleAnim() {
        //ValueAnimator.ofFloat(0, STANDARD_MIN_R, STANDARD_MIN_R + 10);
        AnimatorGroup anim = new AnimatorGroup();

        AnimatorValue anim_1 = new AnimatorValue();
        anim_1.setDuration((long) (mDuration1 / 2.0f));
        anim_1.setValueUpdateListener((animatorValue, v) -> {
            mState = 1;
            mCurValue = (float) STANDARD_MIN_R * v;
            mDifValue = mCurValue - mPreValue;

            // 绿色小球变大
            mSeCurR = (float) mCurValue;
            mSeStrokeWidth = mSeCurR;

            mPreValue = mCurValue;

        });

        AnimatorValue anim_2 = new AnimatorValue();
        anim_2.setDuration((long) (mDuration1 / 2.0f));
        anim_2.setValueUpdateListener((animatorValue, v) -> {
            mState = 1;
            mCurValue = (float) STANDARD_MIN_R + 10 * v;
            mDifValue = mCurValue - mPreValue;

            // 绿色小球内部变大,成为空心
            mSeCurR += mDifValue;
            mSeStrokeWidth = mSeCurR;
            // 黄色圆弧变大
            mFiCurR -= mDifValue / 2;
            mFiStrokeWidth -= mDifValue;

            mPreValue = mCurValue;

        });
        anim.runSerially(anim_1, anim_2);
        return anim;
    }

    /**
     * 第二步:黄色圆环旋转为圆弧,带有一点蓝色的尾巴,逐渐缩短,绿色圆膨胀一些,变为圆环
     */
    protected Animator createRotateAnim() {
        // 内部绿色圆膨胀10
        final int gap = 10;
        // 膨胀速率与角度关系
        final float rate = gap / 180f;
        final Color[] colors = new Color[]{CoolLoadingComponent.TRANSPARENT, CoolLoadingComponent.TRANSPARENT, CoolLoadingComponent.BLUE};
        final float[] positions = new float[]{0, 0.8f, 1};

        mAngle = 0;
        mSweepAngle = 360;
        //ValueAnimator.ofInt(0, 180 + 20);
        AnimatorValue animator = new AnimatorValue();
        animator.setDuration(mDuration2);
        animator.setValueUpdateListener((animatorValue, v) -> {
            mState = 2;
            mCurValue = (int) 200 * v;
            mDifValue = mCurValue - mPreValue;
            if (mCurValue <= 180) {
                mSeCurR += mDifValue * rate / 2;
                mSeStrokeWidth -= mDifValue * rate;

                mAngle = mCurValue * 3;
                mSweepAngle -= mDifValue * 2;
            } else {
                mSweepAngle = 0;
                positions[1] += (mCurValue - 180) * 0.01f;
                mSweepGradient = new SweepShader(getCurX(), getCurY(), colors, positions);
            }

            mPreValue = mCurValue;
        });
        animator.setStateChangedListener(new SimpleAnimatorListener() {
            @Override
            public void onStart(Animator animator) {
                super.onStart(animator);
                // 初始化变量
                mCurValue = 0;
                mPreValue = 0;
                mSweepAngle = 360;
                mRectF = new RectFloat(getCurX() - (MAX_RADIUS_CIRCLE - 5 - mFiStrokeWidth / 2),
                        getCurY() - (MAX_RADIUS_CIRCLE - 5 - mFiStrokeWidth / 2),
                        getCurX() + (MAX_RADIUS_CIRCLE - 5 - mFiStrokeWidth / 2),
                        getCurY() + (MAX_RADIUS_CIRCLE - 5 - mFiStrokeWidth / 2));
                colors[2] = CoolLoadingComponent.BLUE;
                positions[1] = 0.8f;
                mSweepGradient = new SweepShader(getCurX(), getCurY(), colors, positions);
            }
        });
        return animator;
    }

    // 第三步:等待小球的到来,黄色圆弧彻底消失,绿色圆弧变为实心圆
    protected Animator createWaitAndFillAnim() {
        //ValueAnimator.ofInt(0, 10);
        AnimatorValue animator = new AnimatorValue();
        animator.setDuration(mDuration3);
        animator.setValueUpdateListener((animatorValue, v) -> {
            if (!isStart) {
                return;
            }
            mState = 2;
            mCurValue = (int) 10 * v;
            mDifValue = mCurValue - mPreValue;

            mSeCurR -= mDifValue / 2f;
            mSeStrokeWidth += mDifValue;
            mPreValue = mCurValue;
        });
        animator.setStateChangedListener(new SimpleAnimatorListener() {
            @Override
            public void onStart(Animator animator) {
                super.onStart(animator);
                isStart = true;
                mCurValue = 0;
                mPreValue = 0;
            }

            @Override
            public void onEnd(Animator animator) {
                super.onEnd(animator);
                isStart = false;
            }
        });

        return animator;
    }


    // 第四步:填充,等待一会,缩小然后放大
    protected Animator createSmallBiggerAnim() {
        // ValueAnimator.ofInt(0, STANDARD_MIN_R + MAX_RADIUS_CIRCLE);
        AnimatorValue animator = new AnimatorValue();
        animator.setDuration(mDuration4);
        animator.setValueUpdateListener((animatorValue, v) -> {
            if (!isStart) {
                return;
            }
            mState = 2;
            mCurValue = (STANDARD_MIN_R + MAX_RADIUS_CIRCLE) * v;
            mDifValue = mCurValue - mPreValue;
            if (mCurValue <= STANDARD_MIN_R) {
                mSeCurR -= mDifValue / 2f;
                mSeStrokeWidth -= mDifValue / 2f;
            } else {
                mSeCurR += mDifValue / 2f;
            }
            mPreValue = mCurValue;
        });
        animator.setStateChangedListener(new SimpleAnimatorListener() {
            @Override
            public void onStart(Animator animator) {
                super.onStart(animator);
                isStart = true;
                mCurValue = 0;
                mPreValue = 0;
            }

            @Override
            public void onEnd(Animator animator) {
                super.onEnd(animator);
                isStart = false;
            }
        });

        return animator;
    }

    /**
     * 第五步:圆环颜色由内向外拓展为蓝色.颜色由浅逐渐变深,一半的时候,内拓为红色,再到黄色,最后全黄,回到第一步
     */
    protected Animator createColorfulAnim() {
        final float[] positions1 = new float[]{0f, 0f, 0f, 0f};
        final float[] positions2 = new float[]{0f, 0f, 0f, 0f, 0f, 0f};
        final Color[] colors1 = new Color[]{CoolLoadingComponent.YELLOW, CoolLoadingComponent.YELLOW, CoolLoadingComponent.GREEN, CoolLoadingComponent.GREEN};
        final Color[] colors2 = new Color[]{CoolLoadingComponent.YELLOW, CoolLoadingComponent.YELLOW, CoolLoadingComponent.RED, CoolLoadingComponent.RED, CoolLoadingComponent.BLUE, CoolLoadingComponent.BLUE};
        //ValueAnimator.ofInt(0, 100, 200, 300, 400);
        AnimatorValue animator = new AnimatorValue();
        animator.setDuration(mDuration5);
        animator.setValueUpdateListener((animatorValue, v) -> {
            if (!isStart) {
                return;
            }
            mState = 3;
            mCurValue = (int) 400 * v;
            if (mCurValue <= 100) {
                positions1[0] = 0;
                positions1[1] = mCurValue / 100f;
                positions1[2] = positions1[0];
                positions1[3] = 1;
                mRadialGradient = new RadialShader(new Point(getCurX(), getCurY()), mSeCurR + mSeStrokeWidth / 2, positions1, colors1, Shader.TileMode.CLAMP_TILEMODE);
            } else if (mCurValue <= 200) {
                colors1[0] = CoolLoadingComponent.BLUE;
                colors1[1] = CoolLoadingComponent.BLUE;
                colors1[2] = CoolLoadingComponent.YELLOW;
                colors1[3] = CoolLoadingComponent.YELLOW;
                positions1[0] = 0;
                positions1[1] = (mCurValue - 100) / 100f;
                positions1[2] = positions1[0];
                positions1[3] = 1;
                mRadialGradient = new RadialShader(new Point(getCurX(), getCurY()), mSeCurR + mSeStrokeWidth / 2, positions1, colors1, Shader.TileMode.CLAMP_TILEMODE);
            } else {
                positions2[5] = 1;
                positions2[4] = (mCurValue - 200) / 200f + 0.5f;
                positions2[3] = positions2[4];
                positions2[2] = positions2[3] - 0.2f;
                positions2[1] = positions2[2];
                positions2[0] = 0;
                mRadialGradient = new RadialShader(new Point(getCurX(), getCurY()), mSeCurR + mSeStrokeWidth / 2, positions2, colors2, Shader.TileMode.CLAMP_TILEMODE);
            }
        });

        animator.setStateChangedListener(new SimpleAnimatorListener() {
            @Override
            public void onStart(Animator animator) {
                super.onStart(animator);
                mState = 3;
                isStart = true;
                mCurValue = 0;
                mPreValue = 0;
                positions1[1] = 0f;
                positions1[0] = 0f;
                positions2[5] = 0f;
                positions2[4] = 0f;
                positions2[3] = 0f;
                positions2[2] = 0f;
                positions2[1] = 0f;
                positions2[0] = 0f;
                colors1[0] = CoolLoadingComponent.YELLOW;
                colors1[1] = CoolLoadingComponent.YELLOW;
                colors1[2] = CoolLoadingComponent.GREEN;
                colors1[3] = CoolLoadingComponent.GREEN;
                mRadialGradient = new RadialShader(new Point(getCurX(), getCurY()), mSeCurR + mSeStrokeWidth, positions1, colors1, Shader.TileMode.CLAMP_TILEMODE);
            }

            @Override
            public void onEnd(Animator animator) {
                super.onEnd(animator);
                isStart = false;
            }
        });
        return animator;
    }

    /**
     * 过度动画,使弧线宽度回到初始值
     *
     * @return
     */
    protected Animator createPassAnim() {
        final float[] gap = new float[]{0, 0};
        // ValueAnimator.ofFloat(0, 1000);
        AnimatorValue animator = new AnimatorValue();
        animator.setDuration(mDuration6);
        animator.setValueUpdateListener((animatorValue, v) -> {
            if (!isStart) {
                return;
            }
            mState = 1;
            mCurValue = (float) 1000 * v;
            mDifValue = mCurValue - mPreValue;
            mFiCurR += mDifValue * gap[0];
            mFiStrokeWidth += mDifValue * gap[1];
            mPreValue = mCurValue;
        });
        animator.setStateChangedListener(new SimpleAnimatorListener() {
            @Override
            public void onEnd(Animator animator) {
                super.onEnd(animator);
                isStart = false;
            }

            @Override
            public void onStart(Animator animator) {
                super.onStart(animator);
                mState = 1;
                isStart = true;
                mCurValue = 0;
                mPreValue = 0;
                mFiCurR = mSeCurR;
                mFiStrokeWidth = mSeStrokeWidth;
                gap[0] = (MAX_RADIUS_CIRCLE - mFiCurR) / 1000;
                gap[1] = (33 - mFiStrokeWidth) / 1000;
                mSeCurR = 0;
                mSeStrokeWidth = 0;
            }
        });

        return animator;
    }

    @Override
    public void startAnim() {
        super.startAnim();
        mAnimatorSet.start();
    }

    @Override
    protected void initEndAnim() {
        // ValueAnimator.ofFloat(0, 1, 2).
        mEndAnimator = new AnimatorValue();
        mEndAnimator.setDuration(mDuration);
        mEndAnimator.setValueUpdateListener((ani, v) -> {
            float zoroToOne = (float) 2 * v;
            if (zoroToOne <= 1.0f) {
                mCurX = (int) (mPerX + zoroToOne * mEndMovingLength);
                mEndCirIRadius = (int) (MAX_RADIUS_CIRCLE * zoroToOne);
                if (zoroToOne <= 0.5f) {
                    zoroToOne = 2 * zoroToOne;
                } else {
                    zoroToOne = 1 - 2 * (zoroToOne - 0.5f);
                }
                mEndCirMRadius = (int) (MAX_RADIUS_CIRCLE * zoroToOne);
            } else {
                if (!isMoveEnd) {
                    isMoveEnd = true;
                    if (mAnimatorStateListen != null) {
                        mAnimatorStateListen.onMoveEnd();
                    }
                }
                zoroToOne = 2 - zoroToOne;
                mEndCirIRadius = (int) (MAX_RADIUS_CIRCLE * zoroToOne);
                if (zoroToOne >= 0.5f) {
                    zoroToOne = (1.0f - zoroToOne) * 2;
                } else {
                    zoroToOne = zoroToOne * 2;
                }
                mEndCirORadius = (int) (MAX_RADIUS_CIRCLE * zoroToOne);
            }
        });
    }
}
